/*
    Used to test HMC
*/

#include <iostream>
#include <fstream>

#include "run_test.h"
//#include "run_files.h"

#include "function.h"
#include "ZFunction.h"
#include "griewank_function.h"
#include "modifiedgriewank_function.h"
#include "rosenbrock_function.h"
#include "shekel_function.h"
#include "zakharov_function.h"
#include "B2_function.h"


void test_HMC(int argc, char *argv[ ])
{
  char FileFamot1[80]; // used for ZFunction only
  char FileFamot2[80]; // used for ZFunction only
  char OutputDir[80];   // Used to temp store the output directory
  int seed;
  double TempStart, TempStep, TempEnd;
  double SuccessRatio;
  int    StepNumber; // Nmd
  int	   NSample;	  // Nmc number of samples for each run
  double StepLength; // = 0.01; //1e-2;
  int NEachTempRun; // number of runs for each temperature
  int N; // number of degrees of freedom
  int nMin;   // every nMin trajectory will be stored in the container!

  if (argc == 15)
  {
    // required content of input arguments
    //
    // argv[1]     seed
    // argv[2]     temperature start
    // argv[3]     temperature step
    // argv[4]     temperature end
    // argv[5]     metropolis success ratio
    // argv[6]     N_md    (StepNumber)
    // argv[7]     N_mc    (NSample)
    // argv[8]    start step length (StepLength)
    // argv[9]    N_runs  (NEachTempRun)
    // argv[10]    the number of dimensions
    // argv[11]     zmatrix
    // argv[12]     inf data file
    // argv[13]    nMin
    // argv[14]    output dir

    seed = atoi(argv[1]);
    TempStart = atof(argv[2]);
    TempStep = atof(argv[3]);
    TempEnd = atof(argv[4]);
    SuccessRatio = atof(argv[5]);
    StepNumber = atoi(argv[6]);
    NSample = atoi(argv[7]);	 
    StepLength = atof(argv[8]); 
    NEachTempRun = atoi(argv[9]);
    N = atoi(argv[10]);
    strcpy_s(FileFamot1, 80, argv[11]);
    strcpy_s(FileFamot2, 80, argv[12]);
    nMin = atoi(argv[13]);
    strcpy_s(OutputDir, 80, argv[14]);
  }
  
  else if (argc == 1)
  {
    ifstream file("Input/params_hmc.txt");

    if (! file)
    {
      cout << "Cannot open params.in\n";
      exit(1);
    }

    file >> seed >> TempStart >> TempStep
      >> TempEnd >> SuccessRatio
      >> StepNumber >> NSample >> StepLength
      >> NEachTempRun >> N >> FileFamot1 >> FileFamot2 >> nMin >> OutputDir; 

    file.close();
  }
  else
  {
    cout << "Incorrect input.\n";
    exit(1);
  }

  string dir(OutputDir);

  //Function *modgrie = new ModGriewankFunction(N, 10.0);
  Function *ZFuncFamot = new ZFunction(N, FileFamot1, FileFamot2);
  //Function *b2Func = new B2Function(N);
  //Function *grieFunc = new GriewankFunction(N);
  //Function *rosenFunc = new RosenbrockFunction(N);
  //Function *shekelFunc = new ShekelFunction(N);
  //Function *zakFunc = new ZakharovFunction(N);

  cout << "-------------------" << endl
       << "|       HMC       |" << endl
       << "-------------------" << endl;
  cout << "Dimension: " << N << endl << endl;

  //run_HMC(argc, argv, modgrie, string("output/Griewank/Mod/"));
  //run_HMC(argc, argv, ZFuncFamot, string("Output/ZfuncMolecule/Famot/"));
  run_HMC(argc, argv, ZFuncFamot, string("Output/ZfuncMolecule/" + dir + "/"));
  //run_HMC(argc, argv, b2Func, string("output/B2/"));
  //run_HMC(argc, argv, grieFunc, string("output/Griewank/"));
  //run_HMC(argc, argv, rosenFunc, string("output/Rosenbrock/"));
  //run_HMC(argc, argv, shekelFunc, string("output/Shekel/"));
  //run_HMC(argc, argv, zakFunc, string("output/Zakharov/"));
}
